package com.service;

import static com.def.GenericDef.BANK_IN;
import static com.def.GenericDef.EVT_SKIP_OPE;
import static com.def.GenericDef.E_BIS_PATH;
import static com.def.GenericDef.EVT_CHNAGE_LOT;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_BOX;
import static com.def.GenericDef.E_XPSKIPOPE_INPUT_ITEM_EMPT;
import static com.def.GenericDef.E_XPSKIPOPE_INVALIED_BNK_FLG;
import static com.def.GenericDef.E_XPSKIPOPE_INVALIED_LOT_ID;
import static com.def.GenericDef.E_XPSKIPOPE_INVALIED_NOT_EQUAL;
import static com.def.GenericDef.E_XPSKIPOPE_INVALIED_ONE;
import static com.def.GenericDef.E_XPSKIPOPE_INVALIED_TWO;
import static com.def.GenericDef.E_XPSKIPOPE_SKIP_TO_OPE_NOT_EXIST;
import static com.def.GenericDef.LOT_SPLIT_0;
import static com.def.GenericDef.PATH_TYPE_REWK;
import static com.def.GenericDef.PROC_WAIT;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.T_XPSKIPOPE;
import static com.def.GenericDef._NORMAL;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IBisDataDao;
import com.dao.IBisOpeDao;
import com.dao.IBisPathDao;
import com.dao.IRetBoxDao;
import com.dao.IRetPrdInfoDao;
import com.dao.IRetPrdLotDao;
import com.icim.service.ICIMBaseService;
import com.model.Bis_data;
import com.model.Bis_ope;
import com.model.Bis_opeId;
import com.model.Bis_path;
import com.model.Bis_pathId;
import com.model.Bis_pathi;
import com.model.Bis_pathiId;
import com.model.Ret_box;
import com.model.Ret_prd_info;
import com.model.Ret_prd_lot;
import com.model.Ret_prd_lotId;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.SimpleRtnBeen;
import com.tx.Xpskipope.XpskipopeI;
import com.tx.Xpskipope.XpskipopeO;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpskipopeService")
public class XpskipopeService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XpskipopeService.class);
	private static String TX_NAME = T_XPSKIPOPE;

	private XpskipopeI inTrx;
	private XpskipopeO outTrx;
	private Ret_box gRet_box;
	private List<Ret_prd_info> gRet_prd_infoList;
	@Autowired
	private IRetBoxDao retBoxDao;
	
	@Autowired
	private IBisPathDao bisPathDao;

	@Autowired
	private IBisOpeDao bisOpeDao;
	
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	
	@Autowired
	private IRetPrdLotDao retPrdLotDao;
	
	@Autowired
	private IBisDataDao bisDataDao;
	
	private String gszMsgBuf = "";
	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;
	private String gEvtSeqID;
	
	public String subMainProc(String strInMsg) {
		long rtnCode = _NORMAL;
		gszMsgBuf = "";
		String outMsg = "";
		inTrx = new XpskipopeI();
		outTrx = new XpskipopeO();
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		gEvtSeqID = GUIDGenerator.javaGUID();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));

		MqOpe mqOpe = new MqOpe();

		try {
			inTrx = (XpskipopeI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2();
			if (rtnCode != _NORMAL) {
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				retBoxDao.flushCurSession();
			}
		} catch (Exception ex) {
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
			logger.info(outMsg);
			return outMsg;
		}
	}
	
	/**
	 * Check inTrx items
	 * 
	 * @return
	 */
	private long checkInTtx() {
		long rtnCode = _NORMAL;

		if (Util.isSpaceCheck(inTrx.getBox_id())) {
			gszMsgBuf = "箱号[" + inTrx.getBox_id() + "]不能为空！";
			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
		}
//		if (Util.isSpaceCheck(inTrx.getPath_id_fk())) {
//			gszMsgBuf = "工艺路线[" + inTrx.getPath_id_fk() + "]不能为空！";
//			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
//		}
//		if (Util.isSpaceCheck(inTrx.getPath_ver_fk())) {
//			gszMsgBuf = "工艺路线版本[" + inTrx.getPath_ver_fk() + "]不能为空！";
//			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
//		}
//		if (Util.isSpaceCheck(inTrx.getSkip_to_ope())) {
//			gszMsgBuf = "转入站点[" + inTrx.getSkip_to_ope() + "]不能为空！";
//			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
//		}
//		if (Util.isSpaceCheck(inTrx.getSkip_to_ope_ver())) {
//			gszMsgBuf = "转入站点版本[" + inTrx.getSkip_to_ope_ver() + "]不能为空！";
//			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
//		}
//		if (Util.isSpaceCheck(inTrx.getProc_id())) {
//			gszMsgBuf = "转入站点制程代码[" + inTrx.getProc_id() + "]不能为空！";
//			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
//		}
//		if (Util.isSpaceCheck(inTrx.getToolg_id())) {
//			gszMsgBuf = "转入站点设备组代码[" + inTrx.getToolg_id() + "]不能为空！";
//			return E_XPSKIPOPE_INPUT_ITEM_EMPT;
//		}
		return rtnCode;
	}
	/**
	 * Check inTrx items
	 * 
	 * @return
	 */
	private long checkNewlot() {
		long rtnCode = _NORMAL;
		Ret_prd_lotId oret_prd_lotId = new Ret_prd_lotId();
		oret_prd_lotId.setLot_id(inTrx.getOlotid());
		oret_prd_lotId.setLot_splt_id(LOT_SPLIT_0);
		Ret_prd_lot oret_prd_lot = retPrdLotDao.get(oret_prd_lotId);
		
		Ret_prd_lotId nret_prd_lotId = new Ret_prd_lotId();
		nret_prd_lotId.setLot_id(inTrx.getNlotid());
		nret_prd_lotId.setLot_splt_id(LOT_SPLIT_0);
		Ret_prd_lot nret_prd_lot = retPrdLotDao.get(nret_prd_lotId);
		if (null != nret_prd_lot) {
			if(nret_prd_lot.getWo_id_fk().equals(oret_prd_lot.getWo_id_fk())){
				nret_prd_lot.setLot_qty(gRet_prd_infoList.size() + nret_prd_lot.getLot_qty());
				nret_prd_lot.setEvt_usr(inTrx.getEvt_usr());
				nret_prd_lot.setEvt_timestamp(gEvtTimestamp);
				nret_prd_lot.setEvt_time_d(gEvtTimeD);
				retPrdLotDao.update(nret_prd_lot);
				
			    oret_prd_lot.setLot_qty(oret_prd_lot.getLot_qty() - gRet_prd_infoList.size());
			    oret_prd_lot.setEvt_usr(inTrx.getEvt_usr());
			    oret_prd_lot.setEvt_timestamp(gEvtTimestamp);
			    oret_prd_lot.setEvt_time_d(gEvtTimeD);
			    retPrdLotDao.update(oret_prd_lot);
			}else{
				gszMsgBuf = "目标批次["+inTrx.getNlotid()+"]所属工单["+ nret_prd_lot.getWo_id_fk() + "]与原批次["+inTrx.getOlotid()+"]所属工单["+oret_prd_lot.getWo_id_fk()+"]不一致，无法调整!";
				return E_XPSKIPOPE_INVALIED_LOT_ID;
			}
		} else {
		    oret_prd_lot.setLot_qty(oret_prd_lot.getLot_qty() - gRet_prd_infoList.size());
		    oret_prd_lot.setEvt_usr(inTrx.getEvt_usr());
		    oret_prd_lot.setEvt_timestamp(gEvtTimestamp);
		    oret_prd_lot.setEvt_time_d(gEvtTimeD);
		    retPrdLotDao.update(oret_prd_lot);
		    
			nret_prd_lot = new Ret_prd_lot();
			nret_prd_lotId = new Ret_prd_lotId();
			nret_prd_lotId.setLot_id(inTrx.getNlotid());
			nret_prd_lotId.setLot_splt_id(LOT_SPLIT_0);
			nret_prd_lot.setId(nret_prd_lotId);
			nret_prd_lot.setLot_stat(PROC_WAIT);
			nret_prd_lot.setWo_id_fk(oret_prd_lot.getWo_id_fk());
			nret_prd_lot.setLot_qty(gRet_prd_infoList.size());
			nret_prd_lot.setEvt_usr(inTrx.getEvt_usr());
			nret_prd_lot.setEvt_timestamp(gEvtTimestamp);
			nret_prd_lot.setEvt_time_d(gEvtTimeD);
			nret_prd_lot.setStb_timestamp(gEvtTimestamp);

			retPrdLotDao.save(nret_prd_lot);
		}
		return rtnCode;
	}
	/**
	 * Get box info
	 * 
	 * @return
	 */
	private long getRetBoxInfo() {
		gRet_box = new Ret_box();
		gRet_box = retBoxDao.get(inTrx.getBox_id());
		if (null == gRet_box) {
			gszMsgBuf = new NotFoundRtnBeen(inTrx.getBox_id(), Ret_box.class).toString();
			return E_RET_BOX + E_READ_NOT_FOUND;
		}
        if(BANK_IN.equals(gRet_box.getBnk_flg())){
        	gszMsgBuf = "在制品仓的箱子["+ inTrx.getBox_id() + "]无法跳站，请去2600界面返回产线!";
			return E_XPSKIPOPE_INVALIED_BNK_FLG;
        }
		return _NORMAL;
	}
	/**
	 * Get sht list info by box
	 * 
	 * @return
	 */
	private long getPrdListInfo() {
		gRet_prd_infoList = new ArrayList<Ret_prd_info>();
		gRet_prd_infoList = retPrdInfoDao.getShtListInfo(inTrx.getBox_id());
		if (null == gRet_prd_infoList) {
			gszMsgBuf = "箱子 [" + inTrx.getBox_id() + "] 中没有玻璃!";
			return E_XPSKIPOPE_SKIP_TO_OPE_NOT_EXIST;
		}

		return _NORMAL;
	}
	
	/**
	 * check Bis_data
	 * @return
	 */
	private long checkOpeNo(){
		String hql = "FROM Bis_data where data_cate = 'PRST' and data_id in ('" + 
				inTrx.getProc_id() + "','" +
				gRet_prd_infoList.get(0).getNx_proc_id_fk() + "')";
		List<Bis_data> dataList = new ArrayList<Bis_data>();
		dataList = bisDataDao.find(hql);
		if(dataList.isEmpty()){
			gszMsgBuf = "转入站点 [" + inTrx.getProc_id() + "]或者当前站点[" + gRet_prd_infoList.get(0).getNx_proc_id_fk() + 
						"] 工艺类别信息维护不全";
			return E_XPSKIPOPE_INVALIED_TWO;
		}else {
			if(dataList.size() == 1){
				gszMsgBuf = "转入站点 [" + inTrx.getProc_id() + "]或者当前站点[" + gRet_prd_infoList.get(0).getNx_proc_id_fk() + 
							"] 工艺类别信息维护不全";
				return E_XPSKIPOPE_INVALIED_ONE;
			}else {
				String ext_4 = dataList.get(0).getExt_4();
				if(ext_4 == null || "".equals(ext_4)){
					gszMsgBuf = "转入站点 [" + inTrx.getProc_id() + "]或者当前站点[" + gRet_prd_infoList.get(0).getNx_proc_id_fk() + 
								"] 工艺类别信息维护不全";
					return E_XPSKIPOPE_INVALIED_ONE;
				}
				if(!Util.isSpaceCheck(inTrx.getQa_back_flg()) && inTrx.getQa_back_flg().equals("Y")){
					return _NORMAL;
				}
				for (Bis_data bis_data : dataList){
					if(!(ext_4.equals(bis_data.getExt_4()))){
						
						// 跳入站点工艺类别与当前站点不符，不可跳站
						gszMsgBuf = "转入站点 [" + inTrx.getProc_id() + "]工艺类别与当前站点[" + gRet_prd_infoList.get(0).getNx_proc_id_fk() + 
									"] 不符，不可跳站";
						return E_XPSKIPOPE_INVALIED_NOT_EQUAL;
					}
				}
			}
		}
		return _NORMAL;
	}
	
	
	/**
	 * Skip to target ope
	 * 
	 * @return
	 */
	private long skipOpeProc() {
		String nx_pep_lvl;
		StringBuffer cus_sn; 
		int index = 0;
		Bis_path toPath = new Bis_path();
		Bis_pathId nxBisPathId = new Bis_pathId();
//		List<Bis_path> toPathList = new ArrayList<Bis_path>();

//		// Get target path
//		String queryToPath = "FROM Bis_path " +
//				"where id.path_id_fk ='"+ inTrx.getPath_id_fk()
//				+ "' AND id.path_ver_fk = '"+ inTrx.getPath_ver_fk()
//				+ "' AND cr_ope_id_fk = '" + inTrx.getSkip_to_ope()
//				+ "' AND cr_ope_ver_fk = '" + inTrx.getSkip_to_ope_ver() + "' ";
//		toPathList = bisPathDao.find(queryToPath);
//		if (toPathList.isEmpty()) {
//			gszMsgBuf = "转入站点 [" + inTrx.getSkip_to_ope() + "]["
//					+ inTrx.getSkip_to_ope_ver() + "] 在当前工艺路线 ["
//					+ inTrx.getPath_id_fk() + "]["
//					+ inTrx.getPath_ver_fk() + "]中不存在";
//			return E_XPSKIPOPE_SKIP_TO_OPE_NOT_EXIST;
//		}
//
//		toPath = toPathList.get(0);
		
	
		nxBisPathId.setPath_id_fk(inTrx.getPath_id_fk());
		nxBisPathId.setPath_ver_fk(inTrx.getPath_ver_fk());
		nxBisPathId.setCr_ope_no(inTrx.getSkip_to_ope_no());
		toPath = bisPathDao.get(nxBisPathId);
		if (null == toPath) {
			gszMsgBuf = "转入站点 [" + inTrx.getSkip_to_ope() + "]["
					+ inTrx.getSkip_to_ope_ver() + "] 在当前工艺路线 ["
					+ inTrx.getPath_id_fk() + "]["
					+ inTrx.getPath_ver_fk() + "]中不存在";
			return E_XPSKIPOPE_SKIP_TO_OPE_NOT_EXIST;
		}

		// Set prd info
		for (int i = 0; i < gRet_prd_infoList.size(); i++) {
			gRet_prd_infoList.get(i).setNx_path_id_fk(
					toPath.getId().getPath_id_fk());
			gRet_prd_infoList.get(i).setNx_path_ver_fk(
					toPath.getId().getPath_ver_fk());
			gRet_prd_infoList.get(i).setNx_ope_no_fk(
					toPath.getId().getCr_ope_no());
			gRet_prd_infoList.get(i).setNx_ope_id_fk(
					toPath.getCr_ope_id_fk());
			gRet_prd_infoList.get(i).setNx_ope_ver_fk(
					toPath.getCr_ope_ver_fk());
			gRet_prd_infoList.get(i).setNx_proc_id_fk(
					inTrx.getProc_id());
			gRet_prd_infoList.get(i).setNx_toolg_id_fk(
					inTrx.getToolg_id());

			if (!Util.isSpaceCheck(inTrx.getNlotid())){
				gRet_prd_infoList.get(i).setEvt_cate(EVT_CHNAGE_LOT);				
			}else{
				gRet_prd_infoList.get(i).setEvt_cate(EVT_SKIP_OPE);
			}
			gRet_prd_infoList.get(i).setEvt_usr(inTrx.getEvt_usr());
			gRet_prd_infoList.get(i).setEvt_timestamp(gEvtTimestamp);
			gRet_prd_infoList.get(i).setEvt_time_d(gEvtTimeD);
			gRet_prd_infoList.get(i).setEvt_seq_id(gEvtSeqID);
			
			//增加返工品计算逻辑
			if(i == 0){
				Bis_opeId nx_bis_opeId = new Bis_opeId();
				Bis_ope nx_bis_ope = new Bis_ope();
				nx_bis_opeId.setOpe_id(gRet_prd_infoList.get(0).getNx_ope_id_fk());
				nx_bis_opeId.setOpe_ver(gRet_prd_infoList.get(0).getNx_ope_ver_fk());
				
				nx_bis_ope = bisOpeDao.get(nx_bis_opeId);
				nx_pep_lvl = nx_bis_ope.getPep_lvl();
				index = Integer.valueOf(nx_pep_lvl) - 1;
				
				cus_sn = new StringBuffer(gRet_prd_infoList.get(0).getCus_sn());
				int count = 0 ;
				try {
					count = Util.S2I(cus_sn.substring(index, index+1));
				} catch (NumberFormatException e) {
					count = 1 ;
				}
				
				if (count == 0) {
					gRet_prd_infoList.get(0).setOqc_skip_flg("N");
				}else {
					gRet_prd_infoList.get(0).setOqc_skip_flg("Y");

				}

			}else{
				cus_sn = new StringBuffer(gRet_prd_infoList.get(i).getCus_sn());
				int count = 0 ;
				try {
					count = Util.S2I(cus_sn.substring(index, index+1));
				} catch (NumberFormatException e) {
					count = 1 ;
				}
				
				if (count == 0) {
					gRet_prd_infoList.get(i).setOqc_skip_flg("N");
				}else {
					gRet_prd_infoList.get(i).setOqc_skip_flg("Y");
				}
			}			
//			if (!Util.isSpaceCheck(inTrx.getNlotid())){
//			    gRet_prd_infoList.get(i).setLot_id(inTrx.getNlotid());
//			}
			retPrdInfoDao.update(gRet_prd_infoList.get(i));
		}

		// 箱子设定
		gRet_box.setNx_path_id_fk(toPath.getId().getPath_id_fk());
		gRet_box.setNx_path_ver_fk(toPath.getId().getPath_ver_fk());
		gRet_box.setNx_ope_no_fk(toPath.getId().getCr_ope_no());
		gRet_box.setNx_ope_ver_fk(toPath.getCr_ope_ver_fk());
		gRet_box.setNx_ope_id_fk(toPath.getCr_ope_id_fk());
		gRet_box.setNx_proc_id_fk(inTrx.getProc_id());
		gRet_box.setNx_toolg_id_fk(inTrx.getToolg_id());
		gRet_box.setEvt_cate(EVT_SKIP_OPE);
		gRet_box.setEvt_usr(inTrx.getEvt_usr());
		gRet_box.setEvt_timestamp(gEvtTimestamp);
		gRet_box.setEvt_time_d(gEvtTimeD);
//		if (!Util.isSpaceCheck(inTrx.getNlotid())){
//		    gRet_box.setLot_id_fk(inTrx.getNlotid());
//		}
		retBoxDao.update(gRet_box);

		return _NORMAL;
	}
	
	/**
	 * change lot
	 * 
	 * @return
	 */
	private long changelot() {

		// Set prd info
		for (int i = 0; i < gRet_prd_infoList.size(); i++) {

			gRet_prd_infoList.get(i).setEvt_cate(EVT_CHNAGE_LOT);
			gRet_prd_infoList.get(i).setEvt_usr(inTrx.getEvt_usr());
			gRet_prd_infoList.get(i).setEvt_timestamp(gEvtTimestamp);
			gRet_prd_infoList.get(i).setEvt_time_d(gEvtTimeD);
			gRet_prd_infoList.get(i).setEvt_seq_id(gEvtSeqID);
			gRet_prd_infoList.get(i).setLot_id(inTrx.getNlotid());
		
			retPrdInfoDao.update(gRet_prd_infoList.get(i));
		}

		// 箱子设定
		gRet_box.setEvt_cate(EVT_CHNAGE_LOT);
		gRet_box.setEvt_usr(inTrx.getEvt_usr());
		gRet_box.setEvt_timestamp(gEvtTimestamp);
		gRet_box.setEvt_time_d(gEvtTimeD);
        gRet_box.setLot_id_fk(inTrx.getNlotid());

		retBoxDao.update(gRet_box);

		return _NORMAL;
	}
	
	private long subMainProc2() {
		long rtnCode = _NORMAL;
		
		// Check inTrx items
		rtnCode = checkInTtx();
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}		
		
		// Get box info
		rtnCode = getRetBoxInfo();
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}

		// Get sht list info
		rtnCode = getPrdListInfo();
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}
		
		//check new lot_id
		if (!Util.isSpaceCheck(inTrx.getNlotid())){
	     	  rtnCode = checkNewlot();
		      if (rtnCode != _NORMAL) {
			      return rtnCode;
		      }
	     	  rtnCode = changelot();
		      if (rtnCode != _NORMAL) {
			      return rtnCode;
		      }
		}
		
		// check Bis_data by ope_no
		if(!Util.isSpaceCheck(inTrx.getSkip_to_ope())){
		rtnCode = checkOpeNo();
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}
		
		// Skip ope
		rtnCode = skipOpeProc();
		if (rtnCode != _NORMAL) {
			return rtnCode;
		}
		}
		return rtnCode;
	}
}
